capture log close
log using mhi_analysis, replace text
//program:  mhi_analysis.do
//task:    Replication of analyses, figures, and tables 
//project: "Who cares about mental health? Benchmarking the issue importance of mental health for American voters"
//author: Jake Haselswerdt \ 2026-1-13

//program setup
*Note: Requires CES module dataset (CES24_MHI.dta) in and a subfolder named "Exhibits" in the working directory.
version 19
clear all
set linesize 80
macro drop _all
set scheme s1color
set more off

use CES24_MHI.dta, clear
svyset [pw=teamweight]

//Initial results
foreach w in teamweight noweight{
	forvalues l=1/10{
		di "`: label issueshort `l'', `w'"
		reg vote resp_cand_list`l' r_conj_cand_id [pw=`w'], cluster(caseid) 
		est sto issue_`l'_`w'
		di ""
	} 
	
}

//Main conjoint effects - Figure 1
ssc install labutil /*Needed for labmask command in loop*/
foreach w in teamweight noweight{
	forvalues l=1/10{
		qui reg vote resp_cand_list`l' r_conj_cand_id [pw=`w'], ///
		cluster(caseid)
		parmest, label level(95) ///
		format(estimate min95 max95 %8.2f p %8.1e) ///
		saving(issue_`l'_`w', replace)
	}
	use issue_1_`w'.dta, clear
	forvalues l=2/10{
	append using issue_`l'_`w'.dta
	erase issue_`l'_`w'.dta
	}
	drop if parm=="r_conj_cand_id" | parm=="_cons"
	gsort -estimate
	gen parmid=_n
	labmask parmid, values(label)
	eclplot estimate min95 max95 parmid, hori ylabel(1(1)10) ///
	ytitle("") yscale(r(.5 10.5)) ///
	xtitle(Agreement effect on vote choice) estopts(mcolor(red) ///
	xlabel(0(.05).35) xline(0, lpattern(dash) lcolor(gs10)) ///
	mlabel(estimate) mlabpos(12) mlabcol(black))
	gr export Exhibits/importance_`w'95.tif, as(tif) replace
	use CES24_MHI.dta, clear
	erase issue_1_`w'.dta
	svyset [pw=teamweight]
}

*Testing for differences using suest (https://www.statalist.org/forums/forum/general-stata-discussion/general/1509618-comparing-coefficients-across-two-models-same-x-data-but-slightly-different-ys)

foreach w in teamweight noweight{
	svyset [pw=`w']
	forvalues l=2/10{
		qui svy: reg vote resp_cand_list1 r_conj_cand_id
		est sto r1
		qui svy: reg vote resp_cand_list`l' r_conj_cand_id
		est sto r`l'
		qui suest r1 r`l'
		di ""
		di "Mental health vs `: label issueshort `l'' (`w')"
		lincom [r1]: resp_cand_list1 - [r`l']: resp_cand_list`l'
	}
}
svyset [pw=teamweight]

//Heterogeneous effects - Figure 2
global amcelist
global mmlist
foreach v in srhealth4 healthins_cat pid3_clean ideo3_clean educ4 faminc3_short age3 man race4{
	qui sum `v'
	local scalemin=r(min)-.25
	local scalemax=r(max)+.25
	reg vote resp_cand_list1##i.`v' r_conj_cand_id ///
	[pw=teamweight], cluster(caseid)
	est sto het_`v'
	margins, dydx(resp_cand_list1) over(`v')
	marginsplot, title("") plotopts(msize(vsmall)) ytitle("Agreement effect") ///
	ylabel(0(.1).5) yscale(range(-.05 .5)) ///
	xscale(range(`scalemin' `scalemax')) xlabel(, labsize(small)) ///
	yline(0, lpattern(dash) lcolor(gs10)) ///
	level(95) saving(Exhibits/amce_`v'.gph, replace)
	global amcelist "$amcelist Exhibits/amce_`v'.gph"
	margins, over(`v' resp_cand_list1)
	marginsplot, title("") ytitle("Vote probability") ///
	plotopts(msize(vsmall))  ylabel(.2(.2).8) yscale(range(.15 .8)) ///
	yline(.5, lpattern(dash) lcolor(gs10)) ///
	xscale(range(`scalemin' `scalemax')) xlabel(, labsize(small)) /// 
	legend(size(vsmall) symxsize(*.5) symysize(*.5)) ///
	level(95) saving(Exhibits/mm_`v'95.gph, replace)
	global mmlist "$mmlist Exhibits/mm_`v'95.gph"
}
gr combine $amcelist
gr export Exhibits/het_amce95.tif, as(tif) replace
grc1leg $mmlist
gr export Exhibits/het_mm95.tif, as(tif) replace

//Descriptives for S2 Appendix

svy: proportion ZOU300 if r_cand_id==1

svy: proportion vote if r_cand_id==1, over(r_conj_cand_id)
svy: reg vote r_conj_cand_id if r_cand_id==1

dtable [pw=teamweight] if r_cand_id==1, factor(srhealth4 healthins_cat pid3_clean ideo3_clean educ4 faminc3_short age3 man race4, statistics(fvpercent)) sformat("%s %%" fvpercent) export(Exhibits/desc_moderators.docx, as(docx) replace)

dtable if r_cand_id==1 [pw=teamweight], continuous (resp_list*, statistics(mean)) nformat(%9.2f mean) export(Exhibits/desc_policy.docx, as(docx) replace)

//S4 Appendix - full regression results & additional analysis

*Main effects - Table S4.1
putexcel set Exhibits/regressions, replace
putexcel A2="Agreement"
putexcel A3="Table position"
putexcel A4="Constant"
putexcel A6="R-squared"
putexcel A7="F"
putexcel A8="Observations"
forvalues i=1/10{
	est restore issue_`i'_teamweight
	local column=`i'+1
	local column: word `column' of `c(alpha)'
	local issuelabel: variable label resp_cand_list`i'
	putexcel `column'1="`issuelabel'"
	foreach est in resp_cand_list`i' r_conj_cand_id _cons{
		local b_`est': di %4.3f _b[`est']
		local se_`est': di %4.3f _se[`est']
		local cell_`est' "`b_`est'' (`se_`est'')"
	}
	putexcel `column'2="`cell_resp_cand_list`i''"
	putexcel `column'4="`cell__cons'"
	putexcel `column'3="`cell_r_conj_cand_id'"
	putexcel `column'4="`cell__cons'"
	local r2: di %4.3f e(r2)
	local f: di %4.2f e(F)
	local n=e(N)
	putexcel `column'6="`r2'"
	putexcel `column'7="`f'"
	putexcel `column'8="`n'"
}

*Heterogeneous effects by SR health & insurance status - Table S4.2
esttab het_srhealth4 het_healthins_cat using Exhibits/het_health.txt, b(3) se(3) onecell nostar label varwidth(40) nobaselevels interaction(" X ") mtitles("Self-reported health" "Insurance status") scalars("r2 R-squared" "F F" "N N") order(1.resp_cand_list1 r_conj_cand_id) note("Survey weights used. Standard errors clustered by respondent displayed in parentheses. Excluded categories: Fair/poor (1), employer (2).") tab replace

*Heterogeneous effects by partisanship & ideology - Table S4.3
esttab het_pid3_clean het_ideo3_clean using Exhibits/het_politics.txt, b(3) se(3) onecell nostar label varwidth(40) nobaselevels interaction(" X ") mtitles("Party identification" "Ideology") scalars("r2 R-squared" "F F" "N N") order(1.resp_cand_list1 r_conj_cand_id) note("Survey weights used. Standard errors clustered by respondent displayed in parentheses. Excluded categories: Democrat (1), liberal (2).") tab replace

*Heterogeneous effects by education & income - Table S4.4
esttab het_educ4 het_faminc3_short using Exhibits/het_ses.txt, b(3) se(3) onecell nostar label varwidth(40) nobaselevels interaction(" X ") mtitles("Education" "Family income") scalars("r2 R-squared" "F F" "N N") order(1.resp_cand_list1 r_conj_cand_id) note("Survey weights used. Standard errors clustered by respondent displayed in parentheses. Excluded categories: HS/less (1), <$40k (2).") tab replace

*Heterogeneous effects by age, gender, and race/ethnicity - Table S4.5
esttab het_age3 het_man het_race4 using Exhibits/het_demo.txt, b(3) se(3) onecell nostar label varwidth(40) nobaselevels interaction(" X ") mtitles("Age" "Gender (man)" "Race/ethnicity") scalars("r2 R-squared" "F F" "N N") order(1.resp_cand_list1 r_conj_cand_id) note("Survey weights used. Standard errors clustered by respondent displayed in parentheses. Excluded categories: 18-44 (1), No (not a man) (2), White (3).") tab replace

*Mental health issue affect incorporating strength of support/opposition - Table S4.6
reg vote i.resp_cand_list1##i.mhstrong r_conj_cand_id [pw=teamweight], cluster(caseid) 
est sto het_mhstrong

reg vote i.resp_cand_list1##i.mhpolicy4 r_conj_cand_id [pw=teamweight], cluster(caseid) 
est sto het_mhpolicy4

esttab het_mhstrong het_mhpolicy4 using Exhibits/het_mhpolicy.txt, b(3) se(3) onecell nostar label varwidth(40) nobaselevels interaction(" X ") mtitles("Strong vs weak" "Ordinal") scalars("r2 R-squared" "F F" "N N") order(1.resp_cand_list1 r_conj_cand_id) note("Survey weights used. Standard errors clustered by respondent displayed in parentheses. Excluded categories: Weak support/opposition (1), strong opposition (2).") tab replace
	
log close
exit
